/*******************************************************************************
 FileName:      newList.h
 Author:        urey
 Version :      1.0
 Date:          2015年6月16日
 Description:
 History:
 <author>		<time>			<version >      <desc>
 urey        2015年6月16日          1.0          create
 *******************************************************************************/
#ifndef NEWLIST_H_
#define NEWLIST_H_

#define LIST_SUCCESS        0
#define LIST_BASE           ((int)0x85000000)	 /* this may changed by you */
#define LIST_NULL_ERROR     (LIST_BASE + 1)

#include <stddef.h>

typedef struct S_LinkedListNode_
{
    struct S_LinkedListNode_ *prev;
    struct S_LinkedListNode_ *next;
    void *value;
//...more user data
}S_LinkedListNode;

/**
 * LinkedList parent
 */
typedef struct S_LinkedList_
{
  S_LinkedListNode head;
} S_LinkedList;


static inline int linkedListCreate(S_LinkedList* pList)
{
    if(pList == NULL)
    {
        return LIST_NULL_ERROR;
    }
    pList->head.next = &pList->head;
    pList->head.prev = &pList->head;
    pList->head.value = NULL;
    return LIST_SUCCESS;
}


/**
 * first element.
 * if empty list return end
 */
static inline S_LinkedListNode* linkedListGetFirst(S_LinkedList* pList)
{
    if(pList == NULL)
    {
        return NULL;
    }
    return pList->head.next;
}

/**
 * next of last element
 */
static inline S_LinkedListNode* linkedListGetTail(S_LinkedList* pList)
{
    if(pList == NULL)
    {
        return NULL;
    }
    return pList->head.prev;
}

/**
 * insert between elements
 * Caution: not public function!!!!! Never Use this out of this File.
 */
static inline void __linkedListAdd(S_LinkedListNode* pNewNode, S_LinkedListNode* pPrevNode, S_LinkedListNode* pNextNode)
{
    pNextNode->prev = pNewNode;
    pNewNode->next = pNextNode;
    pNewNode->prev = pPrevNode;
    pPrevNode->next = pNewNode;
}

/**
 * delete between elements
 * Caution: not public function!!!!! Never Use this out of this File.
 */
static inline void __linkedListDel(S_LinkedListNode* pPrevNode, S_LinkedListNode* pNextNode)
{
    pNextNode->prev = pPrevNode;
    pPrevNode->next = pNextNode;
}


/**
 * push back
 */
static inline void linkedListAddTail(S_LinkedList* pList, S_LinkedListNode* pNode)
{
/*    S_LinkedListNode* pPrevNode = pList->head.prev;
    S_LinkedListNode* pNextNode = &pList->head;*/
    __linkedListAdd(pNode, pList->head.prev, &pList->head);
}

/**
 * insert at first
 */
static inline void linkedListAddFirst(S_LinkedList* pList, S_LinkedListNode* pNode)
{
    __linkedListAdd(pNode, &pList->head, pList->head.next);
}

/**
 * insert NewNode after another Node
 */
/*
static inline void linkedListAddAfter(S_LinkedListNode* pFrontNode, S_LinkedListNode* pNewNode)
{
    __linkedListAdd(pNewNode, pFrontNode, pFrontNode->next);
}
*/
#define linkedListAddAfter(pFrontNode, pNewNode)  __linkedListAdd(pNewNode, pFrontNode, pFrontNode->next)
/**
 * insert NewNode Before another Node
 */
//static inline void linkedListAddBefore(S_LinkedListNode* pBehindNode, S_LinkedListNode* pNewNode)
//{
//    __linkedListAdd(pNewNode, pBehindNode->prev, pBehindNode);
//}
#define linkedListAddBefore(pBehindNode, pNewNode)  __linkedListAdd(pNewNode, pBehindNode->prev, pBehindNode)

/**
 * remove Node from the LinkedList.
 * you need to free the Node mem and the Value mem by yourself
 */
static inline void linkedListRemoveNode(S_LinkedListNode* pNode)
{
    __linkedListDel(pNode->prev, pNode->next);
    pNode->prev = NULL;
    pNode->next = NULL;
}

/**
 * return true if size is 0
 */
static inline int linkedListIsEmpty(S_LinkedList *pList)
{
    return pList->head.next == &pList->head;
}

/**
 * list_is_last - tests whether @list is the last entry in list @head
 * @list: the entry to test
 * @head: the head of the list
 */
static inline int linkedListIsLast(const S_LinkedList *pList, S_LinkedListNode *pNode)
{
    return &pList->head == pNode->next;
}

/*
 * return the element of the Node
 */
static inline void* linkedListEntry(S_LinkedListNode *pNode)
{
    return pNode->value;
}

#define linkedList_for_each(pNode, pList) \
    for (pNode = (pList)->head.next; pNode != &(pList)->head; pNode = pNode->next)

#define linkedListTail_for_each(pNode, pList) \
    for (pNode = (pList)->head.prev; pNode != &(pList)->head; pNode = pNode->prev)



#endif /* NEWLIST_H_ */
